﻿using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

public enum GameEvent
{
    START_GAME,
    END_GAME

}

public class EventCallBack
{
    protected System.Object[] arguments;  //参数
    protected GameEvent type;  //事件类型
    protected System.Object sender;    //发送者

    // bean函数
    public GameEvent Type
    {
        get { return type; }
        set { type = value; }
    }

    public System.Object[] Params
    {
        get { return arguments; }
        set { arguments = value; }
    }

    public System.Object Sender
    {
        get { return sender; }
        set { sender = value; }
    }

    // 常用函数
    public override string ToString()
    {
        return type + " [ " + ((sender == null) ? "null" : sender.ToString()) + " ] ";
    }

    public EventCallBack Clone()
    {
        return new EventCallBack(type, arguments, sender);
    }

    // 构造函数
    public EventCallBack(GameEvent type)
    {
        Type = type;
    }
    public EventCallBack(GameEvent type, System.Object sender)
    {
        Type = type;
        Sender = sender;
    }
    public EventCallBack(GameEvent type, System.Object[] args, System.Object sender)
    {
        Type = type;
        arguments = args;
        Sender = sender;
    }
}

public delegate void EventListenerDelegate(EventCallBack evt);

public  class EventStruct
{
    private static  EventStruct _ins;
    public static EventStruct Inst {
        get
        {
            if(_ins==null) _ins = new EventStruct();
            return _ins;

        }
    }

    static Dictionary<GameEvent, EventListenerDelegate> notifications = new Dictionary<GameEvent, EventListenerDelegate>(); // 所有的消息
    public static void RegisterListener(GameEvent type, EventListenerDelegate listener)
    {
        if (listener == null)
        {
            Debug.LogError("registerObserver: listener不能为空");
            return;
        }

        // 将新来的监听者加入调用链，这样只要调用Combine返回的监听者就会调用所有的监听者
        Debug.Log("NotifacitionCenter: 添加监视" + type);

        EventListenerDelegate myListener = null;
        notifications.TryGetValue(type, out myListener);
        notifications[type] = (EventListenerDelegate)Delegate.Combine(myListener, listener);
    }
    public static void RemoveListener(GameEvent type, EventListenerDelegate listener)
    {
        if (listener == null)
        {
            Debug.LogError("removeObserver: listener不能为空");
            return;
        }

        // 与添加的思路相同，只是这里是移除操作
        Debug.Log("NotifacitionCenter: 移除监视" + type);
        notifications[type] = (EventListenerDelegate)Delegate.Remove(notifications[type], listener);
    }
    public static  void RemoveAllListeners()
    {
        notifications.Clear();
    }

    public static void Send(GameEvent type,object[] args = null)
    {
        
        if (notifications.ContainsKey(type) == false) return;
        EventCallBack evt = new EventCallBack(type, args, EventStruct.Inst);
        Dispath(evt);
    }

    static void Dispath(EventCallBack evt)
    {
        EventListenerDelegate listenerDelegate;
        if (notifications.TryGetValue(evt.Type, out listenerDelegate))
        {
            try
            {
                if (listenerDelegate != null)
                {
                   // 执行调用所有的监听者
                listenerDelegate(evt);
                }

            }
            catch (System.Exception e)
            {
                throw new Exception(string.Concat(new string[] { "Error dispatching event", evt.Type.ToString(), ": ", e.Message, " ", e.StackTrace }), e);
            }
        }
    }

}
